/*
 * LEDs driver for the "User LED" on Routerboard532
 *
 * Copyright (C) 2009 Phil Sutter <n0-1@freewrt.org>
 *
 * Based on leds-cobalt-qube.c by Florian Fainelly and
 * rb-diag.c (my own standalone driver for both LED and
 * button of Routerboard532).
 */
#include <dt-bindings/gpio/gpio.h> 
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
//#include "rs_gpio.h"

#define LED_DELAY_TIME	400
void set_cbox_in_value(int value);
int get_cbox_in_value(void);
int get_cbox_det_value(void);
void led_pw_flash_open(void);
void led_pw_flash_close(void);

struct rs_gpio {
	int			gpio;
	int			active_low;
};
struct mcc_gpio
{
	struct rs_gpio en;
	struct rs_gpio a0;
	struct rs_gpio a1;
	struct rs_gpio a2;
	struct rs_gpio trigger;
	struct rs_gpio trigger2;
	struct rs_gpio netEn;
	struct rs_gpio fpgaEn;		//led_en_gpio
	struct rs_gpio fpgaRst;
	struct rs_gpio ledEn;
	struct rs_gpio usb1;
	struct rs_gpio usb2;
	struct rs_gpio j13_2;
	struct rs_gpio j13_3;
	struct rs_gpio j13_4;
	struct rs_gpio j13_5;
	struct rs_gpio j13_pwr;
};
const char *rs_led_pw_name  = "led_pw_gpio";
const char *rs_led_red_name  = "led_red_gpio";
const char *rs_cbox_in_name  = "cbox_in_gpio";
const char *rs_cbox_det_name  = "cbox_det_gpio";
const char *rs_wifi_pwr_name  = "wifi_pwr_gpio";
const char *rs_ex5v_drv_name  = "ex5v_drv_gpio";
const char *rs_usb_hub_name  = "usb_hub_gpio";

struct rs_gpio	wifi_pwr_gpio;
struct rs_gpio	led_pw_gpio;
struct rs_gpio	led_red_gpio;
struct rs_gpio	cbox_in_gpio;
struct rs_gpio	cbox_det_gpio;
struct rs_gpio	ex5v_drv_gpio;
struct rs_gpio	usb_hub_gpio;
static struct delayed_work	led_work;
static int led_flag=0;
//static int hub_time=0;
#define CONFIG_MCC_SUPPORT
#ifdef CONFIG_MCC_SUPPORT
struct mcc_gpio	mcc_gpios;
static struct class *mcc_class;
void rs_gpio_set(int io,int val)
{
	if(io>0)
		gpio_set_value(io,val);
	else
		printk("io error %d \n",io);
}
static ssize_t mcc_en_show(struct class *cls, struct class_attribute *attr, char *_buf)
{
	//printk("watch_dog_show buf=%s\n",_buf);
	return sprintf(_buf,"%d",gpio_get_value(mcc_gpios.en.gpio));
}

static ssize_t mcc_en_store(struct class *cls, struct class_attribute *attr, const  char *_buf, size_t _count)
{
	int cmd;

	cmd = simple_strtol(_buf, NULL, 10);
	printk("%s : _buf = %s, cmd = %d\n", __func__, _buf,cmd);
	if(cmd==0)
		rs_gpio_set(mcc_gpios.en.gpio,0);
	else
		rs_gpio_set(mcc_gpios.en.gpio,1);

	return _count;
}
static CLASS_ATTR_RW(mcc_en);
static ssize_t led_en_show(struct class *cls, struct class_attribute *attr, char *_buf)
{
	//printk("watch_dog_show buf=%s\n",_buf);
	return sprintf(_buf,"%d",gpio_get_value(mcc_gpios.ledEn.gpio));
}

static ssize_t led_en_store(struct class *cls, struct class_attribute *attr, const  char *_buf, size_t _count)
{
	int cmd;

	cmd = simple_strtol(_buf, NULL, 10);
	printk("%s : _buf = %s, mcc_gpios.ledEn.gpio=%d cmd = %d\n", __func__, _buf,mcc_gpios.ledEn.gpio,cmd);
	if(cmd==0)
		rs_gpio_set(mcc_gpios.ledEn.gpio,0);
	else if(cmd==1)
		rs_gpio_set(mcc_gpios.ledEn.gpio,1);
	return _count;
}
static CLASS_ATTR_RW(led_en);
static ssize_t fpga_rst_show(struct class *cls, struct class_attribute *attr, char *_buf)
{
	//printk("watch_dog_show buf=%s\n",_buf);
	return sprintf(_buf,"%d",gpio_get_value(mcc_gpios.fpgaRst.gpio));
}

static ssize_t fpga_rst_store(struct class *cls, struct class_attribute *attr, const  char *_buf, size_t _count)
{
	int cmd;

	cmd = simple_strtol(_buf, NULL, 10);
	printk("%s : _buf = %s, mcc_gpios.fpga_en.gpio=%d cmd = %d\n", __func__, _buf,mcc_gpios.fpgaRst.gpio,cmd);
	if(cmd==0)
		rs_gpio_set(mcc_gpios.fpgaRst.gpio,0);
	else if(cmd==1)
		rs_gpio_set(mcc_gpios.fpgaRst.gpio,1);
	else
	{
		rs_gpio_set(mcc_gpios.fpgaRst.gpio,0);
		msleep(100);
		rs_gpio_set(mcc_gpios.fpgaRst.gpio,1);
	}
	return _count;
}
static CLASS_ATTR_RW(fpga_rst);
static ssize_t fpga_en_show(struct class *cls, struct class_attribute *attr, char *_buf)
{
	//printk("watch_dog_show buf=%s\n",_buf);
	return sprintf(_buf,"%d",gpio_get_value(mcc_gpios.fpgaEn.gpio));
}

static ssize_t fpga_en_store(struct class *cls, struct class_attribute *attr, const  char *_buf, size_t _count)
{
	int cmd;

	cmd = simple_strtol(_buf, NULL, 10);
	printk("%s : _buf = %s, mcc_gpios.fpga_en.gpio=%d cmd = %d\n", __func__, _buf,mcc_gpios.fpgaEn.gpio,cmd);
	if(cmd==0)
		rs_gpio_set(mcc_gpios.fpgaEn.gpio,0);
	else if(cmd==1)
		rs_gpio_set(mcc_gpios.fpgaEn.gpio,1);
	return _count;
}
static CLASS_ATTR_RW(fpga_en);
static ssize_t mcc_trigger_show(struct class *cls, struct class_attribute *attr, char *_buf)
{
	//printk("watch_dog_show buf=%s\n",_buf);
	return sprintf(_buf,"%d",gpio_get_value(mcc_gpios.trigger.gpio));
}

static ssize_t mcc_trigger_store(struct class *cls, struct class_attribute *attr, const  char *_buf, size_t _count)
{
	int cmd;

	cmd = simple_strtol(_buf, NULL, 10);
	printk("%s : _buf = %s, cmd = %d\n", __func__, _buf,cmd);
	if(cmd==0)
	{
		rs_gpio_set(mcc_gpios.trigger.gpio,0);
		rs_gpio_set(mcc_gpios.trigger2.gpio,0);
	}
	else
	{
		rs_gpio_set(mcc_gpios.trigger.gpio,1);
		rs_gpio_set(mcc_gpios.trigger2.gpio,1);
	}
	return _count;
}
static CLASS_ATTR_RW(mcc_trigger);
static ssize_t net_en_show(struct class *cls, struct class_attribute *attr, char *_buf)
{
	//printk("watch_dog_show buf=%s\n",_buf);
	//return sprintf(_buf,"%d",gpio_get_value(mcc_gpios.netEn.gpio));
	return sprintf(_buf,"%d",0);	
}

static ssize_t net_en_store(struct class *cls, struct class_attribute *attr, const  char *_buf, size_t _count)
{
	int cmd;

	cmd = simple_strtol(_buf, NULL, 10);
	printk("%s : _buf = %s, cmd = %d  io:%d \n", __func__, _buf,cmd,mcc_gpios.netEn.gpio);
	if(cmd==0)
	{
		rs_gpio_set(mcc_gpios.netEn.gpio,0);
		rs_gpio_set(mcc_gpios.j13_pwr.gpio,0);
	}
	else
	{
		rs_gpio_set(mcc_gpios.netEn.gpio,1);
		rs_gpio_set(mcc_gpios.j13_pwr.gpio,0);
	}

	return _count;
}
static CLASS_ATTR_RW(net_en);
static ssize_t mcc_addr_show(struct class *cls, struct class_attribute *attr, char *_buf)
{
	//printk("watch_dog_show buf=%s\n",_buf);
	return sprintf(_buf,"%d %d %d ",gpio_get_value(mcc_gpios.a0.gpio),gpio_get_value(mcc_gpios.a1.gpio),gpio_get_value(mcc_gpios.a2.gpio));
}

static ssize_t mcc_addr_store(struct class *cls, struct class_attribute *attr, const  char *_buf, size_t _count)
{
	int cmd;
	int abit=0;
	cmd = simple_strtol(_buf, NULL, 10);
	printk("%s : _buf = %s, cmd = %d\n", __func__, _buf,cmd);
	
	abit=cmd&0x01;
	rs_gpio_set(mcc_gpios.a0.gpio,abit);
	abit=(cmd>>1)&0x01;
	rs_gpio_set(mcc_gpios.a1.gpio,abit);
	abit=(cmd>>2)&0x01;
	rs_gpio_set(mcc_gpios.a2.gpio,abit);	
	return _count;
}
static CLASS_ATTR_RW(mcc_addr);
static ssize_t mcc_j13_show(struct class *cls, struct class_attribute *attr, char *_buf)
{
	//printk("watch_dog_show buf=%s\n",_buf);
	return sprintf(_buf,"%d %d %d %d ",gpio_get_value(mcc_gpios.j13_2.gpio),
		gpio_get_value(mcc_gpios.j13_3.gpio),gpio_get_value(mcc_gpios.j13_4.gpio),gpio_get_value(mcc_gpios.j13_5.gpio));
}

static ssize_t mcc_j13_store(struct class *cls, struct class_attribute *attr, const  char *_buf, size_t _count)
{
	int cmd;
	int abit=0;
	cmd = simple_strtol(_buf, NULL, 16);
	printk("%s : _buf = %s, cmd = %x\n", __func__, _buf,cmd);
	abit=cmd&0x01;
	rs_gpio_set(mcc_gpios.j13_2.gpio,abit);
	abit=(cmd>>1)&0x01;
	rs_gpio_set(mcc_gpios.j13_3.gpio,abit);
	abit=(cmd>>2)&0x01;
	rs_gpio_set(mcc_gpios.j13_4.gpio,abit);
	abit=(cmd>>3)&0x01;
	rs_gpio_set(mcc_gpios.j13_5.gpio,abit);
	abit=(cmd>>8)&0x01;
	rs_gpio_set(mcc_gpios.j13_pwr.gpio,abit);	
	return _count;
}
static CLASS_ATTR_RW(mcc_j13);
int create_mcc_class(void)
{
		int ret;
		mcc_class=class_create(THIS_MODULE,"rsio");
		if(!(mcc_class))
		{
			printk("mcc_class fail \n");
		}else{
			ret = class_create_file(mcc_class,&class_attr_mcc_addr);
			if (ret) 
				printk(KERN_ERR "%s:Fail to creat mcc_addr \n", __func__);
			ret = class_create_file(mcc_class,&class_attr_mcc_j13);
			if (ret) 
				printk(KERN_ERR "%s:Fail to creat j13 \n", __func__);
			ret = class_create_file(mcc_class,&class_attr_mcc_en);
			if (ret) 
				printk(KERN_ERR "%s:Fail to creat class_attr_mcc_en \n", __func__);
			ret = class_create_file(mcc_class,&class_attr_mcc_trigger);
			if (ret) 
				printk(KERN_ERR "%s:Fail to creat class_attr_mcc_trigger \n", __func__);
			ret = class_create_file(mcc_class,&class_attr_net_en);
			if (ret) 
				printk(KERN_ERR "%s:Fail to creat class_attr_net_en \n", __func__);
			ret = class_create_file(mcc_class,&class_attr_fpga_en);
			if (ret) 
				printk(KERN_ERR "%s:Fail to creat class_attr_fpga_en \n", __func__);
			ret = class_create_file(mcc_class,&class_attr_fpga_rst);
			if (ret) 
				printk(KERN_ERR "%s:Fail to creat class_attr_fpga_rst \n", __func__);
			ret = class_create_file(mcc_class,&class_attr_led_en);
			if (ret) 
				printk(KERN_ERR "%s:Fail to creat class_attr_led_en \n", __func__);
			printk("Create mcc class success \n");
		}
		return  ret;
}

#endif		//CONFIG_MCC_SUPPORT

static void led_timer_work(struct work_struct *work)		//任务回调函数
{
	if(led_pw_gpio.gpio)
		rs_gpio_set(led_pw_gpio.gpio,led_flag);

	if(led_red_gpio.gpio)
		rs_gpio_set(led_red_gpio.gpio,led_flag);

	//if(hub_time == 15)
	//	rs_gpio_set(usb_hub_gpio.gpio, !usb_hub_gpio.active_low);

	//hub_time++;

	if(led_flag)
		led_flag=0;
	else
		led_flag=1;
	
	schedule_delayed_work(&led_work,msecs_to_jiffies(LED_DELAY_TIME));
}

static int __of_parse_gpio(struct device_node *of_node,const char *propname, struct rs_gpio *gpio)
{
	enum of_gpio_flags flags;
	int gpio_num;

	gpio_num = of_get_named_gpio_flags(of_node, propname, 0, &flags);
	if (gpio_num >= 0)
		gpio->gpio = gpio_num;
	else
		gpio->gpio = -1;

	gpio->active_low = (flags == GPIO_ACTIVE_HIGH)? 1:0;

	printk("%s, gpio = %d\n", __func__, gpio->gpio);
	printk("%s, active low = %d\n", __func__, gpio->active_low);

	return 0;
}

static int __get_gpio_from_of_node(struct platform_device *pdev){
	struct device_node *of_node = pdev->dev.of_node;
	
	__of_parse_gpio(of_node, rs_wifi_pwr_name, &wifi_pwr_gpio);
	__of_parse_gpio(of_node, rs_led_red_name, &led_red_gpio);
	__of_parse_gpio(of_node, rs_led_pw_name, &led_pw_gpio);
	__of_parse_gpio(of_node, rs_cbox_in_name,  &cbox_in_gpio);
	__of_parse_gpio(of_node, rs_cbox_det_name,  &cbox_det_gpio);
	__of_parse_gpio(of_node, rs_ex5v_drv_name, &ex5v_drv_gpio);
	__of_parse_gpio(of_node, rs_usb_hub_name, &usb_hub_gpio);
#ifdef CONFIG_MCC_SUPPORT
	__of_parse_gpio(of_node, "mcc_en_gpio", &mcc_gpios.en);
	__of_parse_gpio(of_node, "j13_en2_gpio", &mcc_gpios.j13_2);
	__of_parse_gpio(of_node, "j13_en3_gpio", &mcc_gpios.j13_3);
	__of_parse_gpio(of_node, "j13_en4_gpio", &mcc_gpios.j13_4);
	__of_parse_gpio(of_node, "j13_en5_gpio", &mcc_gpios.j13_5);
	__of_parse_gpio(of_node, "j13_pwr_gpio", &mcc_gpios.j13_pwr);
	__of_parse_gpio(of_node, "mcc_a0_gpio", &mcc_gpios.a0);
	__of_parse_gpio(of_node, "mcc_a1_gpio", &mcc_gpios.a1);
	__of_parse_gpio(of_node, "mcc_a2_gpio", &mcc_gpios.a2);
	__of_parse_gpio(of_node, "mcc_trigger_gpio", &mcc_gpios.trigger);
	__of_parse_gpio(of_node, "mcc_trigger_gpio2", &mcc_gpios.trigger2);
	__of_parse_gpio(of_node, "net_en_gpio", &mcc_gpios.netEn);
	__of_parse_gpio(of_node, "fpga_en_gpio", &mcc_gpios.fpgaEn);
	__of_parse_gpio(of_node, "fpga_rst_gpio", &mcc_gpios.fpgaRst);
	__of_parse_gpio(of_node, "led_en_gpio", &mcc_gpios.ledEn);
	__of_parse_gpio(of_node, "usb1_en_gpio", &mcc_gpios.usb1);
	__of_parse_gpio(of_node, "usb2_en_gpio", &mcc_gpios.usb2);
#endif	
	return 0;
	
}

static int request_gpio_in(struct rs_gpio *gpio){
	int ret;
	
	if(gpio->gpio > 0){
		ret = gpio_request(gpio->gpio, NULL);
		if (ret != 0) {
			gpio_free(gpio->gpio);
			printk(KERN_ERR "request %d pin fail!\n", gpio->gpio);
			return -1;
		}else{
			gpio_direction_input(gpio->gpio);
		}		
	}else{
		ret=-1;
		printk(KERN_ERR "request gpio not exist!\n");
	}
	return ret;
}

static int request_gpio_out(struct rs_gpio *gpio){
	int ret;
	
	if(gpio->gpio > 0){
		ret = gpio_request(gpio->gpio, NULL);
		if (ret != 0) {
			gpio_free(gpio->gpio);
			printk(KERN_ERR "request %d pin fail!\n", gpio->gpio);
			return -1;
		}else{
			gpio_direction_output(gpio->gpio, gpio->active_low);
			printk(KERN_ERR "request %d pin Success \n", gpio->gpio);
		}		
	}else{
		ret=-1;
		printk(KERN_ERR "request gpio not exist!\n");
	}

	return ret;
}

/*
void set_gpio0_value(int value){
	if(-1 < value && value < 2 && value != wifi_pwr_gpio.active_low){
		wifi_pwr_gpio.active_low =  value;
		gpio_direction_output(wifi_pwr_gpio.gpio, wifi_pwr_gpio.active_low);
	}
}

int get_gpio0_value(void){
	return wifi_pwr_gpio.active_low;
}*/

void set_cbox_in_value(int value){
	if(-1 < value && value < 2 && value != cbox_in_gpio.active_low){
		cbox_in_gpio.active_low =  value;
		gpio_direction_output(cbox_in_gpio.gpio, cbox_in_gpio.active_low);
	}
}

int get_cbox_in_value(void){
	return cbox_in_gpio.active_low;
}

int get_cbox_det_value(void){
	return gpio_get_value(cbox_det_gpio.gpio);
}
void led_pw_flash_open()  
{
	INIT_DELAYED_WORK(&led_work, led_timer_work);
	schedule_delayed_work(&led_work,msecs_to_jiffies(LED_DELAY_TIME));
}

void led_pw_flash_close(){

	//if(usb_hub_gpio.gpio)
	//	rs_gpio_set(usb_hub_gpio.gpio, !usb_hub_gpio.active_low);

	cancel_delayed_work(&led_work);

	if(led_pw_gpio.gpio)
		rs_gpio_set(led_pw_gpio.gpio, led_pw_gpio.active_low);	
	
	if(led_red_gpio.gpio)
		rs_gpio_set(led_red_gpio.gpio, led_red_gpio.active_low);
	
}

static const struct of_device_id of_power_leds_match[] = {
	{ .compatible = "rs,gpio", },
//	{ .compatible = "pwm-fan", },	
	{},
};


static int rs_gpio_suspend(struct platform_device *pdev, pm_message_t state)
{
	if(led_red_gpio.gpio > 0)
		rs_gpio_set(led_red_gpio.gpio, !led_red_gpio.active_low);	
	
	return 0;
}

static int rs_gpio_resume(struct platform_device *pdev)
{
	if(led_red_gpio.gpio > 0)
		rs_gpio_set(led_red_gpio.gpio, led_red_gpio.active_low);	
	
	return 0;
}

/*
static void rs_gpio_shutdown(struct platform_device *_dev)
{
	printk("rs_gpio_shutdown\n");
	
	//msleep(2000);
	
	if(wifi_pwr_gpio.gpio > 0)
		rs_gpio_set(wifi_pwr_gpio.gpio, !wifi_pwr_gpio.active_low);
}*/

static int rs_gpio_probe(struct platform_device *pdev)
{
	printk("%s probe \n",__func__);
	__get_gpio_from_of_node(pdev);
	request_gpio_out(&wifi_pwr_gpio);
	request_gpio_out(&led_pw_gpio);
	request_gpio_out(&led_red_gpio);
	request_gpio_out(&cbox_in_gpio);
	request_gpio_in(&cbox_det_gpio);
	request_gpio_out(&ex5v_drv_gpio);
	request_gpio_out(&usb_hub_gpio);

#ifdef CONFIG_RS_GPIO_LED_PW_FLASH
	if(led_pw_gpio.gpio > 0)
		led_pw_flash_open();	
#endif

	if(wifi_pwr_gpio.gpio > 0){
		rs_gpio_set(wifi_pwr_gpio.gpio, !wifi_pwr_gpio.active_low);
		//msleep(1000);
		rs_gpio_set(wifi_pwr_gpio.gpio, wifi_pwr_gpio.active_low);
	}
	if(ex5v_drv_gpio.gpio>0)
	{
		rs_gpio_set(ex5v_drv_gpio.gpio, ex5v_drv_gpio.active_low);
		printk("ex5v_drv_gpio %d \n",ex5v_drv_gpio.gpio);
	}
#ifdef CONFIG_MCC_SUPPORT
	request_gpio_out(&mcc_gpios.en);
	request_gpio_out(&mcc_gpios.a0);
	request_gpio_out(&mcc_gpios.a1);
	request_gpio_out(&mcc_gpios.a2);
	request_gpio_out(&mcc_gpios.trigger);
	request_gpio_out(&mcc_gpios.trigger2);
	request_gpio_out(&mcc_gpios.netEn);
	request_gpio_out(&mcc_gpios.fpgaEn);
	request_gpio_out(&mcc_gpios.fpgaRst);
	request_gpio_out(&mcc_gpios.ledEn);
	request_gpio_out(&mcc_gpios.usb1);
	request_gpio_out(&mcc_gpios.usb2);
	request_gpio_out(&mcc_gpios.j13_pwr);
	request_gpio_out(&mcc_gpios.j13_2);
	request_gpio_out(&mcc_gpios.j13_3);
	request_gpio_out(&mcc_gpios.j13_4);
	request_gpio_out(&mcc_gpios.j13_5);

	if(mcc_gpios.en.gpio>0)
	{
		printk("mcc_en_gpio %d \n",mcc_gpios.netEn.gpio);
		rs_gpio_set(mcc_gpios.en.gpio, 1);
		printk("mcc_en_gpio %d \n",mcc_gpios.en.gpio);
	}
	if(mcc_gpios.ledEn.gpio>0)
	{
		printk("ledEn_gpio %d \n",mcc_gpios.ledEn.gpio);
		rs_gpio_set(mcc_gpios.ledEn.gpio, 1);
		printk("ledEn %d \n",mcc_gpios.ledEn.gpio);
	}
	if(mcc_gpios.fpgaEn.gpio>0)
	{
	//	rs_gpio_set(mcc_gpios.fpgaEn.gpio, 0);
	//	mdelay(100);
	//	rs_gpio_set(mcc_gpios.fpgaEn.gpio, 1);
		printk("fpgaEn %d \n",mcc_gpios.fpgaEn.gpio);
	}
	if(mcc_gpios.fpgaRst.gpio>0)
	{
	//	rs_gpio_set(mcc_gpios.fpgaRst.gpio, 0);
	//	mdelay(100);
	//	rs_gpio_set(mcc_gpios.fpgaRst.gpio, 1);
		printk("fpgaRst %d \n",mcc_gpios.fpgaRst.gpio);
	}
	if(mcc_gpios.usb1.gpio>0)
	{
	//	rs_gpio_set(mcc_gpios.fpgaEn.gpio, 0);
			rs_gpio_set(mcc_gpios.usb1.gpio, 0);
		rs_gpio_set(mcc_gpios.usb2.gpio, 0);
	//	mdelay(300);
		rs_gpio_set(mcc_gpios.usb1.gpio, 1);
		rs_gpio_set(mcc_gpios.usb2.gpio, 1);
		printk("usbio  %d  %d \n",mcc_gpios.usb1.gpio,mcc_gpios.usb2.gpio);
	}
		rs_gpio_set(mcc_gpios.a0.gpio,1);
		rs_gpio_set(mcc_gpios.a1.gpio,0);
		
//Create class file
		create_mcc_class();		
#endif
	return 0;
}

static int rs_gpio_remove(struct platform_device *pdev)
{
	
	if(wifi_pwr_gpio.gpio > 0) gpio_free(wifi_pwr_gpio.gpio);
	if(led_pw_gpio.gpio > 0) gpio_free(led_pw_gpio.gpio);
	if(led_red_gpio.gpio > 0) gpio_free(led_red_gpio.gpio);
	if(cbox_in_gpio.gpio > 0) gpio_free(cbox_in_gpio.gpio);
	if(cbox_det_gpio.gpio > 0) gpio_free(cbox_det_gpio.gpio);
	if(ex5v_drv_gpio.gpio > 0) gpio_free(ex5v_drv_gpio.gpio);
	if(usb_hub_gpio.gpio > 0) gpio_free(usb_hub_gpio.gpio);
	if(mcc_gpios.usb1.gpio>0)
	{
		rs_gpio_set(mcc_gpios.usb1.gpio,0);
		rs_gpio_set(mcc_gpios.usb2.gpio,0);
	}

	//rs_gpio_set(mcc_gpios.j13_2.gpio,0);
//	msleep(200);
//	rs_gpio_set(mcc_gpios.j13_3.gpio,0);	msleep(200);
//	rs_gpio_set(mcc_gpios.j13_4.gpio,0);	msleep(200);
//	rs_gpio_set(mcc_gpios.j13_5.gpio,0);	msleep(200);
//	rs_gpio_set(mcc_gpios.fpgaEn.gpio,0);

	return 0;
}

static struct platform_driver rs_gpio_driver = {
	.probe = rs_gpio_probe,
	.remove = rs_gpio_remove,
	.suspend = rs_gpio_suspend,
	.resume = rs_gpio_resume,
	//.shutdown = rs_gpio_shutdown,
	.driver = {
		.name = "rs-gpio",
		.owner = THIS_MODULE,
		.of_match_table = of_match_ptr(of_power_leds_match),
	},
};

static int __init rs_gpio_init(void)
{
	return platform_driver_register(&rs_gpio_driver);
}

static void __exit rs_gpio_exit(void)
{
	platform_driver_unregister(&rs_gpio_driver);
}
//early_initcall(rs_gpio_init)
module_init(rs_gpio_init);
module_exit(rs_gpio_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("User RS support for gpio");
MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>");
MODULE_ALIAS("platform:rs-gpio");
